//
//  YCAuthorityUtil.m
//  YCBaseModule
//
//  Created by Apple on 2022/11/8.
//

#import "YCAuthorityUtil.h"
#import <Photos/Photos.h>
#import <Contacts/Contacts.h>
#import <CoreLocation/CoreLocation.h>
#import <CoreBluetooth/CoreBluetooth.h>
#import <CoreTelephony/CTCellularData.h>
#import <UserNotifications/UserNotifications.h>
#import <Speech/Speech.h>
#import <EventKit/EventKit.h>

@interface YCAuthorityUtil ()<CLLocationManagerDelegate, CBCentralManagerDelegate>

@property (nonatomic, copy) void (^locationCompletion)(BOOL status);
@property (nonatomic, strong) CLLocationManager *locationManager;
@property (nonatomic, copy) void (^centralCompletion)(BOOL status);
@property (nonatomic, strong) CBCentralManager *centralManager;

@end

@implementation YCAuthorityUtil

+ (instancetype)manager {
    static YCAuthorityUtil *single = nil;
    static dispatch_once_t once;
    dispatch_once(&once, ^{
        single = [[[self class] alloc] init];
    });
    return single;
}

- (void)getAuthorForNetwork:(void (^)(BOOL status))completion {
    CTCellularData *cellularData = [[CTCellularData alloc] init];
    CTCellularDataRestrictedState authState = cellularData.restrictedState;
    
    if (authState == kCTCellularDataRestrictedStateUnknown) {
        cellularData.cellularDataRestrictionDidUpdateNotifier = ^(CTCellularDataRestrictedState state){
            if (state == kCTCellularDataNotRestricted) {
                dispatch_async(dispatch_get_main_queue(), ^{
                    if (completion) {
                        completion(YES);
                    }
                });
            } else {
                dispatch_async(dispatch_get_main_queue(), ^{
                    if (completion) {
                        completion(NO);
                    }
                });
            }
        };
    } else if (authState == kCTCellularDataNotRestricted){
        if (completion) {
            completion(YES);
        }
    } else {
        if (completion) {
            completion(NO);
        }
    }
}

- (void)getAuthorForCamera:(void(^)(BOOL status))completion {
    AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
    
    if (authStatus == AVAuthorizationStatusAuthorized) {
        if (completion) {
            completion(YES);
        }
    }
    else if (authStatus == AVAuthorizationStatusNotDetermined) {
        [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
            dispatch_async(dispatch_get_main_queue(), ^{
                if (granted) {
                    if (completion) {
                        completion(YES);
                    }
                } else {
                    if (completion) {
                        completion(NO);
                    }
                }
            });
        }];
    }
    else {
        if (completion) {
            completion(NO);
        }
    }
}

- (void)getAuthorForPhotoLibrary:(void(^)(BOOL status))completion {
    PHAuthorizationStatus authStatus = [PHPhotoLibrary authorizationStatus];
    
    if (authStatus == PHAuthorizationStatusAuthorized)
    {
        if (completion) {
            completion(YES);
        }
    }
    else if (authStatus == PHAuthorizationStatusNotDetermined)
    {
        [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
            dispatch_async(dispatch_get_main_queue(), ^{
                
                if (status == PHAuthorizationStatusAuthorized) {
                    if (completion) {
                        completion(YES);
                    }
                } else {
                    if (completion) {
                        completion(NO);
                    }
                }
            });
        }];
    }
    else
    {
        if (completion) {
            completion(NO);
        }
    }
}

- (void)getAuthorForContact:(void(^)(BOOL status))completion {
    CNAuthorizationStatus authStatus = [CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts];
    
    if (authStatus == CNAuthorizationStatusAuthorized) {
        if (completion) {
            completion(YES);
        }
    }
    else if (authStatus == CNAuthorizationStatusNotDetermined) {
        CNContactStore *store = [[CNContactStore alloc] init];
        [store requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError*  _Nullable error) {
            
            dispatch_async(dispatch_get_main_queue(), ^{
                if (granted) {
                    if (completion) {
                        completion(YES);
                    }
                } else {
                    if (completion) {
                        completion(NO);
                    }
                }
            });
        }];
    }
    else {
        if (completion) {
            completion(NO);
        }
    }
}

- (void)getAuthorForLocation:(void(^)(BOOL status))completion {
    CLAuthorizationStatus authStatus = [CLLocationManager authorizationStatus];
    
    if (authStatus == kCLAuthorizationStatusAuthorizedAlways || authStatus == kCLAuthorizationStatusAuthorizedWhenInUse) {
        if (completion) {
            completion(YES);
        }
    }
    else if (authStatus == kCLAuthorizationStatusNotDetermined) {
        self.locationCompletion = completion;
        self.locationManager = [[CLLocationManager alloc] init];
        self.locationManager.delegate = self;
        [self.locationManager requestWhenInUseAuthorization];
    }
    else {
        if (completion) {
            completion(NO);
        }
    }
}

- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {
    switch (status) {
        case kCLAuthorizationStatusNotDetermined:
            break;
        case kCLAuthorizationStatusAuthorizedAlways:
        case kCLAuthorizationStatusAuthorizedWhenInUse: {
            if (self.locationCompletion) {
                self.locationCompletion(YES);
            }
        }
            break;
        default: {
            if (self.locationCompletion) {
                self.locationCompletion(NO);
            }
        }
            break;
    }
}

- (void)getAuthorForBluetooth:(void(^)(BOOL status))completion {
    CBPeripheralManagerAuthorizationStatus authStatus = [CBPeripheralManager authorizationStatus];
    
    if (authStatus == CBPeripheralManagerAuthorizationStatusNotDetermined) {
        self.centralCompletion = completion;
        self.centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
        [self.centralManager scanForPeripheralsWithServices:nil options:nil];
        
    } else if (authStatus == CBPeripheralManagerAuthorizationStatusAuthorized) {
        if (completion) {
            completion(YES);
        }
    } else {
        if (completion) {
            completion(NO);
        }
    }
}

- (void)centralManagerDidUpdateState:(CBCentralManager *)central {
    CBPeripheralManagerAuthorizationStatus authStatus = [CBPeripheralManager authorizationStatus];
    if (authStatus == CBPeripheralManagerAuthorizationStatusAuthorized) {
        if (self.centralCompletion) {
            self.centralCompletion(YES);
        }
    } else {
        if (self.centralCompletion) {
            self.centralCompletion(NO);
        }
    }
}

- (void)getAuthorForMicrophone:(void(^)(BOOL status))completion {
    AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeAudio];
    
    if (authStatus == AVAuthorizationStatusNotDetermined) {
        [AVCaptureDevice requestAccessForMediaType:AVMediaTypeAudio completionHandler:^(BOOL granted) {
            dispatch_async(dispatch_get_main_queue(), ^{
                if (granted) {
                    if (completion) {
                        completion(YES);
                    }
                } else {
                    if (completion) {
                        completion(NO);
                    }
                }
            });
        }];
        
    } else if(authStatus == AVAuthorizationStatusAuthorized){
        if (completion) {
            completion(YES);
        }
    } else {
        if (completion) {
            completion(NO);
        }
    }
}

- (void)getAuthorForPush:(void(^)(BOOL status))completion {
    [[UNUserNotificationCenter currentNotificationCenter] requestAuthorizationWithOptions:UNAuthorizationOptionBadge | UNAuthorizationOptionSound | UNAuthorizationOptionAlert | UNAuthorizationOptionCarPlay completionHandler:^(BOOL granted, NSError * _Nullable error) {
            dispatch_async(dispatch_get_main_queue(), ^{
                if (granted) {
                    if (completion) {
                        completion(YES);
                    }
                } else {
                    if (completion) {
                        completion(NO);
                    }
                }
            });
        }];
}

- (void)getAuthorForSpeech:(void(^)(BOOL status))completion {
    SFSpeechRecognizerAuthorizationStatus authStatus = [SFSpeechRecognizer authorizationStatus];
    
    if (authStatus == SFSpeechRecognizerAuthorizationStatusNotDetermined) {
        [SFSpeechRecognizer requestAuthorization:^(SFSpeechRecognizerAuthorizationStatus status) {
            dispatch_async(dispatch_get_main_queue(), ^{
                if (status == SFSpeechRecognizerAuthorizationStatusAuthorized) {
                    if (completion) {
                        completion(YES);
                    }
                } else {
                    if (completion) {
                        completion(NO);
                    }
                }
            });
        }];
    } else if (authStatus == SFSpeechRecognizerAuthorizationStatusAuthorized) {
        if (completion) {
            completion(YES);
        }
    } else {
        if (completion) {
            completion(NO);
        }
    }
}

- (void)getAuthorForEvent:(void (^)(BOOL status))completion {
    EKEventStore *eventStore = [[EKEventStore alloc] init];
    [eventStore requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError * _Nullable error) {
        dispatch_async(dispatch_get_main_queue(), ^{
            if (granted) {
                if (completion) {
                    completion(YES);
                }
            } else {
                if (completion) {
                    completion(NO);
                }
            }
        });
    }];
}

@end
